package com.xmd.red.service;

import com.xmd.red.bean.RedPacket;
import com.xmd.red.config.WxConfig;
import com.xmd.red.dao.RedPacketDao;
import com.xmd.red.utils.WxPayRequest;
import com.xmd.red.utils.WxPayResponse;
import com.xmd.red.utils.WxUtil;
import okhttp3.*;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;

/**
 * Created by superbone on 2016/11/2.
 */
@Service
public class SendService {

    private final String echeck_name = "NO_CHECK";
    private final String edesc = "东楚风红包";
    private final String emch_appid = "wx7b623dbd28c7d792";
    private final String emchid = "1376582702";
    private final String certUrl = "d:/key/cert/apiclient_cert.p12";
    private final String ekey = "G8Y0o9cNalyNB8bx7AHU2CkrWOSKLet7";
    private final String eurl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    private Logger log = LoggerFactory.getLogger(SendService.class);

    private long initTime = 0;

    @Resource
    private RedPacketDao dao;
    @Resource
    private WxConfig wxConfig;

    //@Scheduled(cron="0 * * * * *")

    //每次执行完后1000ms执行下一次.
    //@Scheduled(fixedDelay = 1000)
    public void execute(){

        Date date = new Date(initTime);
        List<RedPacket> list = dao.findNeedSend(date);

        FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
        log.info(fdf.format(date));

        if(list.size()==0){
            log.info("循环一轮结束");
            initTime = 0;
            return;
        }


        for(RedPacket record : list){
            initTime = record.getCreateTime().getTime();
            transferSync(record);
        }
    }

    private void transferSync(RedPacket record){


        List<RedPacket> redPackets = dao.queryDeviceIdList(record.getDeviceId());

        /**
         *  设备编号记录数超过1条
         *  处理重复申请的情况:
         *      如果设备号查询出来的数据多余1条.
         *      则判断是否有发送成功的记录,如果有.则把其他的申请记录状态设置成2.
         *      然后本次方法执行结束
         *      如果没有发送成功的记录,继续执行发送的操作,下次再碰到相同的设备,则会被上面的判断过滤
         */

        if(record.getOpenId().equalsIgnoreCase(wxConfig.getTestOpenId())) {

            //do nothing!!
        }else{

            if(redPackets.size()>0){
                boolean isSend = false;
                for(RedPacket r : redPackets){
                    if(r.getState()==3){
                        isSend = true;
                        break;
                    }
                }
                if(isSend){
                    log.info("该设备已经发放过红包.不做重复发送");
                    for(RedPacket r : redPackets){
                        if(r.getState()!=3){
                            r.setState(2);
                            dao.save(r);
                        }
                    }
                    return;
                }
            }
        }

        WxPayRequest request = new WxPayRequest();
        int amount = (int)(record.getTotal()*100);
        request.setAmount(amount);
        request.setCheck_name(echeck_name);
        request.setDesc(edesc);
        request.setMch_appid(emch_appid);
        request.setMchid(emchid);
        request.setNonce_str(String.valueOf(record.getId()));
        request.setOpenid(record.getOpenId());
        request.setPartner_trade_no(String.valueOf(record.getId()));
        request.setSpbill_create_ip(record.getClientIp());

        File certFile = new File(certUrl);
        if(!certFile.exists()){
            return;
        }
        InputStream is = null;
        SSLSocketFactory socketFactory = null;
        MediaType mediaType = MediaType.parse("text/xml");
        try{

            request = WxUtil.sign(request, ekey);
            String xml = WxUtil.toXml(request);


            is = new FileInputStream(certFile);
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(is, emchid.toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(keyStore, emchid.toCharArray());
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, null);
            socketFactory = sslContext.getSocketFactory();
            OkHttpClient client = null;
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            if(socketFactory!=null){
                client = builder.sslSocketFactory(socketFactory,new MyX509TrustManager()).build();
            }else{
                client = builder.build();
            }
            RequestBody requestBody = RequestBody.create(mediaType, xml.getBytes("UTF-8"));
            Request okRequest = new Request.Builder().url(eurl).post(requestBody).build();
            Response response = client.newCall(okRequest).execute();
            if(!response.isSuccessful()){
                record.setState(1);
                log.info("微信支付接口调用失败");
            }else{
                String result = response.body().string();
                WxPayResponse wxResponse = WxUtil.toObj(result, WxPayResponse.class);
                String errCode = wxResponse.getErr_code();
                String errCodeDes = wxResponse.getErr_code_des();
                if (wxResponse.getReturn_code().equalsIgnoreCase("SUCCESS")
                        && wxResponse.getResult_code().equalsIgnoreCase("SUCCESS")){
                    record.setState(3);
                    log.info("openId:" + record.getOpenId() + " 支付成功");
                }else{
                    // 余额不足,状态还是为1
                    if (errCode.equalsIgnoreCase("NOTENOUGH")) {
                        record.setState(1);
                    } else {
                        record.setState(2);
                    }
                    record.setErrCode(errCode);
                    record.setErrCodeDes(errCodeDes);
                    log.info("openId:" + record.getOpenId() + " 余额不足,支付失败");
                }
            }
            record.setLastUpdateTime(new Date());
            dao.save(record);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class MyX509TrustManager implements X509TrustManager {

    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    public X509Certificate[] getAcceptedIssuers() {

        X509Certificate[] x509Certificates = new X509Certificate[0];
        return x509Certificates;
    }
}
